package com.futu.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.futu.common.enums.ApiServiceExceptionEnum;
import com.futu.common.utils.SnowflakeIdWorker;
import com.futu.common.utils.TokenUtils;
import com.futu.common.vo.ResultVo;
import com.futu.scenicspot.domain.HScenicSpot;
import com.futu.scenicspot.service.HScenicSpotService;
import com.futu.user.domain.Role;
import com.futu.user.domain.Users;
import com.futu.user.domain.YPrice;
import com.futu.user.domain.YReserve;
import com.futu.user.dto.LoginDto;
import com.futu.user.dto.PhoneLoginDto;
import com.futu.user.mapper.RoleMapper;
import com.futu.user.service.UsersService;
import com.futu.user.mapper.UsersMapper;
import com.futu.user.service.YPriceService;
import com.futu.user.service.YReserveService;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
* @author yuu
* @description 针对表【Users(用户表)】的数据库操作Service实现
* @createDate 2025-06-04 20:46:32
*/
@Service
public class UsersServiceImpl extends ServiceImpl<UsersMapper, Users>
    implements UsersService{

    @Autowired
    private UsersMapper usersMapper;
    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private YReserveService yReserveService;

    @Autowired
    private HScenicSpotService hScenicSpotService;

    @Autowired
    private YPriceService yPriceService;

    @Override
    public ResultVo login(LoginDto dto) throws InterruptedException {

        if (dto.getPassword()==null)
        {
            return ResultVo.error(ApiServiceExceptionEnum.RESULT_ERROR);
        }
        if (dto.getUsername()==null)
        {
            return ResultVo.error(ApiServiceExceptionEnum.RESULT_ERROR);
        }
        SnowflakeIdWorker worker = new SnowflakeIdWorker(1, 1);
        RLock lock = redissonClient.getLock(dto.getUsername());
        boolean b = lock.tryLock(3, TimeUnit.SECONDS);
        if (b) {
            try {

                Users user = usersMapper.selectOne(new LambdaQueryWrapper<Users>().eq(Users::getUsername, dto.getUsername()));
                if (user == null) {
                    Users user1 = new Users();
                    user1.setUserId(worker.nextId());
                    user1.setUsername(dto.getUsername());

                    String salt = UUID.randomUUID().toString().substring(0, 15);
                    user1.setSalt(salt);
                    user1.setPassword(DigestUtils.md5DigestAsHex((dto.getPassword() + salt).getBytes()));
                    user1.setPhoneNumber(dto.getPhone());
                    user1.setEmail(dto.getEmail());
                    user1.setNickname(dto.getUsername());;
                    user1.setRegistrationTime(new Date());
                    user1.setLastLoginTime(new Date());
                    user1.setStatus(1);
                    user1.setPoits(0);
                    user1.setMembershipLevelId(1l);
                    user1.setMembershipExpiryDate(new Date());
                    user1.setCreatedAt(new Date());
                    user1.setUpdatedAt(new Date());

                    boolean save = this.save(user1);
                    if (save) {
                        String token = TokenUtils.createJwtToken(user1.getUserId().toString());
                        redisTemplate.opsForValue().set("user" + user1.getUserId().toString(), token);
                        return ResultVo.success(token);
                    } else {
                        return ResultVo.error(ApiServiceExceptionEnum.RESULT_ERROR);
                    }

                } else {
                    if (dto.getPassword() != null) {
                        String password = DigestUtils.md5DigestAsHex((dto.getPassword() + user.getSalt()).getBytes());
                        if (password.equals(user.getPassword())) {
                            String token = TokenUtils.createJwtToken(user.getUserId().toString());
                            redisTemplate.opsForValue().set("user" + user.getUserId().toString(), token);
                            return ResultVo.success(token);
                        } else {
                            return ResultVo.error(ApiServiceExceptionEnum.Login_ERROR);
                        }
                    }
                }
            } catch (Exception e) {
                log.error("不允许重复点击"+e.getMessage());
            }finally {
                if (lock.isHeldByCurrentThread()&&b)
                {
                    lock.unlock();
                }
            }
        }

        return ResultVo.error(ApiServiceExceptionEnum.Login_ERROR);
    }

    @Override
    public ResultVo loginAndRegister(String phone) {
        if (phone == null || phone.isEmpty()) {
            return ResultVo.error(ApiServiceExceptionEnum.PARAM_ERROR);
        }
        
        try {
            // 查询手机号是否已注册
            Users user = usersMapper.selectOne(new LambdaQueryWrapper<Users>().eq(Users::getPhoneNumber, phone));
            
            if (user == null) {
                // 未注册，创建新用户
                SnowflakeIdWorker worker = new SnowflakeIdWorker(1, 1);
                Users newUser = new Users();
                newUser.setUserId(worker.nextId());
                newUser.setUsername("user_" + phone);
                newUser.setPhoneNumber(phone);
                newUser.setNickname("用户_" + phone.substring(phone.length() - 4));
                
                // 默认密码处理
                String salt = UUID.randomUUID().toString().substring(0, 15);
                newUser.setSalt(salt);
                String defaultPassword = DigestUtils.md5DigestAsHex(("123456" + salt).getBytes());
                newUser.setPassword(defaultPassword);
                
                // 设置其他默认值
                newUser.setRegistrationTime(new Date());
                newUser.setLastLoginTime(new Date());
                newUser.setStatus(1);
                newUser.setPoits(0);
                newUser.setMembershipLevelId(1L);
                newUser.setMembershipExpiryDate(new Date());
                newUser.setCreatedAt(new Date());
                newUser.setUpdatedAt(new Date());
                
                boolean saved = this.save(newUser);
                if (saved) {
                    // 生成token
                    String token = TokenUtils.createJwtToken(newUser.getUserId().toString());
                    redisTemplate.opsForValue().set("user" + newUser.getUserId().toString(), token);
                    return ResultVo.success(token);
                } else {
                    return ResultVo.error("用户注册失败");
                }
            } else {
                // 已注册，直接登录
                String token = TokenUtils.createJwtToken(user.getUserId().toString());
                redisTemplate.opsForValue().set("user" + user.getUserId().toString(), token);
                return ResultVo.success(token);
            }
        } catch (Exception e) {
            log.error("手机号注册/登录失败: " + e.getMessage(), e);
            return ResultVo.error("登录失败，请稍后重试");
        }
    }

    @Override
    public ResultVo phoneLogin(PhoneLoginDto phoneLoginDto) throws InterruptedException {
        if (phoneLoginDto == null || phoneLoginDto.getPhone() == null || phoneLoginDto.getPhone().isEmpty()) {
            return ResultVo.error(ApiServiceExceptionEnum.PARAM_ERROR);
        }
        
        String phone = phoneLoginDto.getPhone();
        RLock lock = redissonClient.getLock("phone_" + phone);
        boolean acquired = lock.tryLock(3, TimeUnit.SECONDS);
        
        if (acquired) {
            try {
                // 查询手机号是否存在
                Users user = usersMapper.selectOne(new LambdaQueryWrapper<Users>().eq(Users::getPhoneNumber, phone));
                
                if (user == null) {
                    return ResultVo.error("该手机号未注册，请先注册");
                } else {
                    // 生成token并返回
                    String token = TokenUtils.createJwtToken(user.getUserId().toString());
                    redisTemplate.opsForValue().set("user" + user.getUserId().toString(), token);
                    user.setLastLoginTime(new Date());
                    this.updateById(user);
                    return ResultVo.success(token);
                }
            } catch (Exception e) {
                log.error("手机号登录失败: " + e.getMessage(), e);
                return ResultVo.error("登录失败，请稍后重试");
            } finally {
                if (lock.isHeldByCurrentThread() && acquired) {
                    lock.unlock();
                }
            }
        }
        
        return ResultVo.error("登录请求过于频繁，请稍后重试");
    }

    @Override
    public ResultVo my(String token) {
        if (token != null)
        {
            Users user = usersMapper.selectOne(new LambdaQueryWrapper<Users>().eq(Users::getUserId, TokenUtils.getUserId(token)));
            if (user != null)
            {
                Role role = roleMapper.selectOne(new LambdaQueryWrapper<Role>().eq(Role::getUserId, user.getUserId()));
                if (role != null)
                {
                    user.setRoleName(role.getName());
                    return ResultVo.success(user);
                }
                return ResultVo.success(user);
            }
        }
        return ResultVo.error(ApiServiceExceptionEnum.RESULT_ERROR);
    }

    @Override
    public ResultVo Reserve(YReserve reserve,String token) {
        // 参数校验
        if (reserve == null) {
            return ResultVo.error(ApiServiceExceptionEnum.PARAM_ERROR);
        }

        if (reserve.getAttractionId() == null) {
            return ResultVo.error("景点ID不能为空");
        }

        if (reserve.getVisitDate() == null) {
            return ResultVo.error("参观日期不能为空");
        }

        if (!StringUtils.hasText(reserve.getPersonCount())) {
            return ResultVo.error("参观人数不能为空");
        }

        if (!StringUtils.hasText(reserve.getContactName())) {
            return ResultVo.error("联系人姓名不能为空");
        }

        if (!StringUtils.hasText(reserve.getContactPhone())) {
            return ResultVo.error("联系人电话不能为空");
        }

        // 查询景点信息
        HScenicSpot scenicSpot = hScenicSpotService.getById(reserve.getAttractionId());
        if (scenicSpot == null) {
            return ResultVo.error("景点不存在");
        }

        // 查询景点价格
        YPrice price = yPriceService.getOne(new LambdaQueryWrapper<YPrice>()
                .eq(YPrice::getSpotId, reserve.getAttractionId()));
        if (price == null) {
            return ResultVo.error("景点价格信息不存在");
        }

        // 生成预订ID（如RSV20250620001）
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String dateStr = sdf.format(reserve.getVisitDate());

        // 设置预订时间为当前时间
        reserve.setReservationTime(new Date());

        // 生成唯一ID
        SnowflakeIdWorker worker = new SnowflakeIdWorker(1, 1);
        reserve.setId(worker.nextId());

        // 保存预订信息
        boolean saved = yReserveService.save(reserve);
        if (saved) {
            // 构建返回的预订信息
            return ResultVo.success("预订成功，预订编号：RSV" + dateStr + String.format("%03d", reserve.getId() % 1000));
        } else {
            return ResultVo.error("预订失败，请稍后重试");
        }
    }
}




